home *** CD-ROM | disk | FTP | other *** search
- ;==========================================================================
- ; STRINGZ.ASM
- ;
- ; C-callable routines that offer string handling capabilities similar
- ; to those found in BASIC, and then some.
- ;
- ; None of the routines in this file allocate memory for, or check for
- ; overflow in copying to, destination strings. It is the responsibility
- ; of the calling routine to insure that enough space is available for
- ; the destination strings, including terminating null bytes.
- ;
- ; Assembler: Borland TASM 1.01 (tasm /ml/t/w2/z stringz;)
- ;
- ; INCON source files and the object and library files created from
- ; them are:
- ; Copyright (c) 1993-94, Richard Zigler.
- ; You may freely distribute unmodified source, object, and library
- ; files, and incorporate them into your own non-commercial software,
- ; provided that this paragraph and the copyright string defined in
- ; INCON.C are included in all copies.
- ;==========================================================================
- ; Function Prototypes
- ;
- ; The string pointer and function return types are all declared
- ; "far", so that these routines can be linked with programs under
- ; any memory model. The functions in this source file can handle
- ; strings up to 32,767 bytes long.
- ;
- ; char far * pascal far LeftStr ( char far *, char far *, short );
- ; char far * pascal far RightStr ( char far *, char far *, short );
- ; char far * pascal far MidStr ( char far *, char far *, short, short );
- ; char far * pascal far lJust ( char far *, char far *, short, short );
- ; char far * pascal far rJust ( char far *, char far *, short, short );
- ; char far * pascal far cJust ( char far *, char far *, short, short );
- ; char far * pascal far lTrim ( char far *, char far * );
- ; char far * pascal far rTrim ( char far *, char far * );
- ; char far * pascal far ReplStr ( char far *, char far *, short, short );
- ; char far * pascal far InsStr ( char far *, char far *, short, short );
- ; char far * pascal far TemplStr ( char far *, char far *, short );
- ;==========================================================================
-
- locals ;enable TASM local symbols
- model small, pascal ;set PASCAL stack handling
-
- ;--------------------------------------------------------------------------
- ; Macros to push registers at entry and pop registers at exit.
- ;--------------------------------------------------------------------------
-
- @PushRegs macro reglist
- ifnb <reglist>
- irp reg, <reglist>
- push reg
- endm
- endif
- endm
-
- @PopRegs macro reglist
- ifnb <reglist>
- irp reg, <reglist>
- pop reg
- endm
- endif
- endm
-
- .code
-
- ;--------------------------------------------------------------------------
- ; LeftStr
- ;
- ; Copies Num characters from left end of SrcStr to DestStr; returns
- ; pointer to DestStr.
- ;
- ; If Num is greater than or equal to the length of SrcStr, all of
- ; SrcStr is copied. If Num is outside the range 1 to 32767, DestStr
- ; is returned null.
- ;--------------------------------------------------------------------------
-
- public LEFTSTR
- LEFTSTR proc far
-
- arg Num :word ;characters to copy
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type Num + type SrcStr + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- mov dx, es ;save for return
- mov bx, di
- mov ax, [Num] ;# chars to move
- and ax, ax
- jle @@Term
- lds si, [SrcStr]
- call StrLen ;CX = source length
- cmp cx, ax
- jle @@Move
- mov cx, ax
- @@Move:
- rep movsb
- @@Term:
- sub al, al
- stosb
- mov ax, bx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- LEFTSTR endp
-
- ;--------------------------------------------------------------------------
- ; RightStr
- ;
- ; Copies Num characters from right end of SrcStr to DestStr; returns
- ; pointer to DestStr.
- ;
- ; If Num is greater than or equal to the length of SrcStr, all of
- ; SrcStr is copied. If Num is outside the range 1 to 32767, DestStr
- ; is returned null.
- ;--------------------------------------------------------------------------
-
- public RIGHTSTR
- RIGHTSTR proc far
-
- arg Num :word ;characters to copy
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type Num + type SrcStr + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- lds si, [SrcStr]
- call StrLen ;CX = source length
- and cx, cx
- jle @@Term ;if out of range
- mov bx, cx ;else save in BX
- mov dx, cx ; and DX
- mov cx, [Num] ;# chars to copy
- and cx, cx
- jle @@Term ;if Num out of range
- sub dx, cx ;else if length > Num
- jg @@NumChars ; move Num characters
- mov cx, bx ;else move length chrs
- jmp short @@Move
- @@NumChars:
- add si, dx ;start at length - Num
- @@Move:
- rep movsb
- @@Term:
- sub al, al
- stosb ;plant null terminator
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- RIGHTSTR endp
-
- ;--------------------------------------------------------------------------
- ; MidStr
- ;
- ; Copies Num characters from SrcStr to DestStr beginning at Start in
- ; SrcStr; returns pointer to DestStr.
- ;
- ; If Start is greater than the length of SrcStr, DestStr is returned
- ; null. If Num is greater than the remainder of SrcStr, all characters
- ; from Start to the end of SrcStr are copied. If either Start or Num
- ; is outside the range 1 to 32767, DestStr is returned null.
- ;--------------------------------------------------------------------------
-
- public MIDSTR
- MIDSTR proc far
-
- arg Num :word ;characters to copy
- arg Start :word ;start position
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type Num + type Start + type SrcStr
- ParmSize = ParmSize + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- mov bx, [Start]
- and bx, bx
- jle @@Term ;if Start <= 0
- mov dx, [Num]
- and dx, dx
- jle @@Term ;if Num <= 0
- lds si, [SrcStr] ;else load source
- call StrLen ;CX = source length
- and cx, cx
- jle @@Term ;if out of range
- cmp bx, cx
- jg @@Term ;if Start > length
- dec bx ; adjust Start for 0,
- sub cx, bx ; adjust length,
- add si, bx ; and move pointer
- cmp dx, cx ;if Num >= length
- jge @@Move ; move length chars
- xchg cx, dx ;else move Num chars
- @@Move:
- rep movsb
- @@Term:
- sub al, al
- stosb ;plant null terminator
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- MIDSTR endp
-
- ;--------------------------------------------------------------------------
- ; lJust
- ;
- ; Copies SrcStr to DestStr, left justified in a field of Size
- ; characters returns pointer to DestStr.
- ;
- ; DestStr is padded on the right with Chr. Chr may be any character,
- ; including control codes. Control codes behave as they normally would,
- ; either printing a graphics character or taking a specific action.
- ; If the length of SrcStr is greater than Size, SrcStr is truncated on
- ; the right. If Size is outside the range 1 to 32767, DestStr is
- ; returned null. If SrcStr is null, DestStr is filled with Size
- ; repetitions of Chr.
- ;--------------------------------------------------------------------------
-
- public LJUST
- LJUST proc far
-
- arg Chr :word ;fill character
- arg Size :word ;field Size
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type Chr + type Size + type SrcStr
- ParmSize = ParmSize + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- mov bx, [Size]
- and bx, bx ;if Size out of range
- jle @@Term ; DestStr returned null
- lds si, [SrcStr] ;load source string
- call StrLen ;CX = source length
- mov al, byte ptr [Chr] ;get fill character
- and cx, cx ;if bad length
- jle @@PutChr ; fill DestStr with Chr
- cmp cx, bx ;if length >= Size
- jge @@SizeBytes ; truncate source string
- sub bx, cx ;else Size -= length
- jmp short @@Move
- @@SizeBytes:
- mov cx, bx ;CX = Size
- sub bx, bx ;0 for @@PutChr
- @@Move:
- rep movsb
- @@PutChr:
- mov cx, bx ;CX = Size
- rep stosb ;fill DestStr with Chr
- @@Term:
- sub al, al
- stosb ;plant null terminator
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- LJUST endp
-
- ;--------------------------------------------------------------------------
- ; rJust
- ;
- ; Copies SrcStr to DestStr, right justified in a field of Size
- ; characters returns pointer to DestStr.
- ;
- ; DestStr is padded on the left with Chr. Chr may be any character,
- ; including control codes. Control codes behave as they normally
- ; would, either printing a graphics character or taking a specific
- ; action. If the length of SrcStr is greater than Size, SrcStr is
- ; truncated on the right. If Size is outside the range 1 to 32767,
- ; DestStr is returned null. If SrcStr is null, DestStr is filled
- ; with Size repetitions of Chr.
- ;--------------------------------------------------------------------------
-
- public RJUST
- RJUST proc far
-
- arg Chr :word ;fill character
- arg Size :word ;field Size
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type Chr + type Size + type SrcStr
- ParmSize = ParmSize + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- mov bx, [Size] ;get Size
- and bx, bx ;if Size <= 0
- jle @@Term ; DestStr returned null
- mov dx, bx ;save Size
- lds si, [SrcStr] ;load source string
- call StrLen ;CX = source length
- and cx, cx ;if <= 0
- jle @@PutChr ; fill DestStr with Chr
- sub bx, cx ;pad = Size - Length
- jle @@SizeBytes ;truncate source
- call SameStr
- lahf ;save ZF
- call OpenLeft
- @@PutChr:
- mov al, byte ptr [Chr]
- xchg cx, bx ;CX = pad
- rep stosb ;fill left end
- and bx, bx ;check SrcStr length
- jle @@Term ;if 0, all done
- sahf ;restore ZF
- jz @@Same
- xchg cx, bx ;CX = source length
- rep movsb
- @@Same:
- add di, bx
- sub al, al
- stosb ;plant null terminator
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- @@SizeBytes:
- mov cx, dx ;CX = Size
- rep movsb
- @@Term:
- sub al, al
- stosb ;plant null terminator
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- RJUST endp
-
- ;--------------------------------------------------------------------------
- ; cJust
- ;
- ; Copies SrcStr to DestStr, centered in a field of Size characters;
- ; returns pointer to DestStr.
- ;
- ; DestStr is padded on the left and right with Chr. Chr may be any
- ; character, with no provision for excluding ASCII control codes.
- ; If the total padding required to center SrcStr is odd, the extra
- ; character is added on the right. If the length of SrcStr is greater
- ; than Size, SrcStr is truncated on the right. If Size is outside the
- ; range 1 to 32767, DestStr is returned null. If SrcStr is null,
- ; DestStr is filled with Size repetitions of Chr.
- ;--------------------------------------------------------------------------
-
- public CJUST
- CJUST proc far
-
- arg Chr :word ;fill character
- arg Size :word ;field Size
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type Chr + type Size + type SrcStr
- ParmSize = ParmSize + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- lds si, [SrcStr] ;load source string
- call SameStr
- pushf ;save ZF
- mov bx, [Size]
- and bx, bx ;if Size out of range
- jle @@Term ; DestStr returned null
- mov dx, bx ;save Size
- mov al, byte ptr [Chr]
- call StrLen ;CX = source length
- and cx, cx ;if 0 < length < 32768
- jg @@LeftPad ; calculate pad needed
- sub cx, cx ;if length >= 32768
- jmp short @@LeftJust ; fill dest with Chr
- @@LeftPad:
- sub bx, cx ;if Size <= length
- jle @@SizeBytes ; truncate source
- shr bx, 1 ;BX = Size / 2
- lahf ;save remainder
- mov dx, bx ;save quotient
- call OpenLeft
- @@LeftJust:
- xchg cx, bx ;get left padding
- rep stosb ;fill left end
- xchg cx, bx ;get back source length
- jcxz @@Term ;if no source, all done
- popf
- jz @@NoMove ;if source/dest identical
- rep movsb
- @@NoMove:
- add di, cx
- mov cx, dx ;CX = remaining dest
- sahf ;restore remainder
- adc cx, bx
- rep stosb ;fill right end
- sub al, al
- stosb ;plant null terminator
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- @@SizeBytes:
- mov cx, dx ;get back Size
- rep movsb
- @@Term:
- sub al, al
- stosb ;plant null terminator
- popf ;clear from stack
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- CJUST endp
-
- ;--------------------------------------------------------------------------
- ; lTrim
- ;
- ; Copies SrcStr to DestStr with leading spaces and control characters
- ; removed. Returns pointer to DestStr.
- ;--------------------------------------------------------------------------
-
- public LTRIM
- LTRIM proc far
-
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type SrcStr + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- lds si, [SrcStr]
- call StrLen ;CX = source length
- and cx, cx
- jle @@Term ;if length out of range
- @@ChkLoop:
- lodsb ;take a byte of source
- and al, al
- jz @@Term ;if end-of-string null
- dec cx ;decrement length
- cmp al, 20h ;char <= ASCII space?
- jbe @@ChkLoop ;unsigned comparison
- cmp al, 7Fh
- je @@ChkLoop ;if [Backspace]
- stosb ;else store first byte
- rep movsb ; and move the rest
- @@Term:
- sub al, al
- stosb ;plant null terminator
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- LTRIM endp
-
- ;--------------------------------------------------------------------------
- ; rTrim
- ;
- ; Copies SrcStr to DestStr with trailing spaces and control characters
- ; removed. Returns pointer to DestStr.
- ;--------------------------------------------------------------------------
-
- public RTRIM
- RTRIM proc far
-
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type SrcStr + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- lds si, [SrcStr]
- call StrLen ;CX = source length
- and cx, cx
- jle @@Term ;if out of range
- mov bx, si ;save SrcStr
- add si, cx ;else bump pointer
- dec si ; and adjust for zero
- inc cx ;for @@ChkLoop
- sub ax, ax
- std ;process strings "down"
- @@ChkLoop:
- dec cx
- lodsb ;take a byte of source
- cmp al, 20h ;char <= ASCII space?
- jbe @@ChkLoop ;unsigned comparison
- cmp al, 7Fh
- je @@ChkLoop ;if [Backspace]
- @@Move:
- mov si, bx
- cld
- rep movsb
- @@Term:
- sub al, al
- stosb
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- RTRIM endp
-
- ;--------------------------------------------------------------------------
- ; ReplStr
- ;
- ; Replaces characters in DestStr with those from SrcStr. Returns pointer
- ; to DestStr.
- ;
- ; If Start is greater than the length of DestStr, ScrStr is
- ; concatenated to DestStr. If DestStr is null, SrcStr is copied
- ; to DestStr. If Start or the length of SrcStr is outside the range
- ; 1 to 32767, DestStr is returned null. If the length of DestStr
- ; will grow so that it crosses a segment boundary, DestStr is
- ; returned null. If SrcStr and DestStr are identical, DestStr is
- ; returned unchanged.
- ;--------------------------------------------------------------------------
-
- public REPLSTR
- REPLSTR proc far
-
- arg Start :word ;start position
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type Start + type SrcStr + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- mov ax, es ;get ptr in DS:SI
- mov ds, ax ; for StrLen()
- mov si, di
- call StrLen
- mov bx, cx ;BX = DestStr length
- lds si, [SrcStr] ;DS:SI->SrcStr
- call SameStr
- jz @@Exit ;if strings identical
- call StrLen ;CX = SrcStr length
- and cx, cx
- jle @@Term ;if length <= 0
- mov dx, [Start]
- and dx, dx
- jle @@Term ;if Start <= 0
- dec dx ;adjust for 0
- cmp dx, bx
- jle @@CheckSize ;if Start <= length
- mov dx, bx ;else Start = length
- @@CheckSize:
- mov ax, dx ;AX = start
- add ax, cx ;AX += source length
- jc @@Term ;if DestStr will wrap
- add ax, di ;AX += DestStr
- jc @@Term ;if DestStr will wrap
- add di, dx ;DI->start
- add dx, cx ;DX = Start + SrcStr len
- rep movsb ;SrcStr=>DestStr
- cmp dx, bx
- jg @@Term ;if DestStr grew
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- @@Term:
- sub al, al ;terminate DestStr
- stosb
- @@Exit:
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- REPLSTR endp
-
- ;--------------------------------------------------------------------------
- ; InsStr
- ;
- ; Inserts characters from SrcStr into DestStr. Returns pointer to
- ; DestStr.
- ;
- ; If Start is greater than the length of DestStr, ScrStr is
- ; concatenated to DestStr. If DestStr is null, SrcStr is copied
- ; to DestStr. If Start or the length of SrcStr is outside the range
- ; 1 to 32767, DestStr is returned null. If the length of DestStr
- ; will grow so that it crosses a segment boundary, DestStr is
- ; returned null. If SrcStr and DestStr are identical, DestStr is
- ; returned unchanged.
- ;--------------------------------------------------------------------------
-
- public INSSTR
- INSSTR proc far
-
- arg Start :word ;start position
- arg SrcStr :far ptr byte ;source string
- arg DestStr :far ptr byte ;destination string
-
- ParmSize = type Start + type SrcStr + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- mov ax, es ;get ptr in DS:SI
- mov ds, ax ; for StrLen()
- mov si, di
- call StrLen
- mov bx, cx ;BX = DestStr length
- lds si, [SrcStr] ;DS:SI->SrcStr
- call SameStr
- jz @@Exit ;if strings identical
- mov dx, [Start]
- and dx, dx
- jle @@Term ;if Start <= 0
- dec dx ;adjust for 0
- call StrLen ;CX = SrcStr length
- and cx, cx
- jle @@Term ;if length <= 0
- cmp dx, bx
- jle @@CheckSize ;if Start <= dest length
- mov dx, bx ;else Start = dest length
- @@CheckSize:
- sub bx, dx ;BX = DestStr length to move
- ;
- ; Check whether DestStr + DestStr length +
- ; SrcStr length will wrap around the segment.
- ;
- mov ax, bx ;AX = dest length past Start
- add ax, cx ;AX += source length
- jc @@Term ;if DestStr will wrap
- add ax, di ;AX += DestStr
- jc @@Term ;if DestStr will wrap
- add di, dx ;ES:DI->Start
- xchg cx, bx ;CX=length/BX=distance
- call OpenLeft
- xchg cx, bx ;CX = SrcStr length
- @@MoveSrc:
- rep movsb ;SrcStr=>DestStr
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- @@Term:
- sub al, al
- stosb
- @@Exit:
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- INSSTR endp
-
- ;--------------------------------------------------------------------------
- ; TemplStr
- ;
- ; Copies characters from SrcStr into DestStr. Returns pointer to
- ; DestStr.
- ;
- ; At entry, DestStr points to a template to be filled in with
- ; characters from SrcStr and Chr is a marker in DestStr that
- ; indicates where those characters go. Note that Chr must NOT
- ; occur in DestStr except as a marker for characters from SrcStr.
- ; For example, in the template "(999) 999-9999" Chr should be "9".
- ; Since " ", "(", ")", and "-" are part of the template, they
- ; would not be suitable as markers. TemplStr moves characters
- ; from SrcStr to DestStr in order, continuing until SrcStr is
- ; exhausted or the end of DestStr is reached. If SrcStr and
- ; DestStr are identical, DestStr is returned unchanged.
- ;--------------------------------------------------------------------------
-
- public TEMPLSTR
- TEMPLSTR proc far
-
- arg Chr :word ;flag character
- arg SrcStr :far ptr byte ;data string
- arg DestStr :far ptr byte ;format string
-
- ParmSize = type Chr + type SrcStr + type DestStr
-
- @PushRegs <si, di, ds>
- mov dx, ParmSize
- les di, [DestStr]
- call NullPtr
- push es ;save for return
- push di
- lds si, [SrcStr] ;DS:SI->SrcStr
- call SameStr
- jz @@Exit ;if strings identical
- mov ah, byte ptr [Chr]
- sub bl, bl ;for cmp ES:[DI], 0
- dec di
- @@Loop:
- lodsb
- and al, al
- jz @@Exit ;if end of SrcStr
- @@ChkFlag:
- inc di
- cmp ah, es:[di]
- jne @@ChkEnd ;if ES:[DI] != flag char
- stosb ;else store char from SrcStr
- dec di
- jmp @@Loop ; and continue
- @@ChkEnd:
- cmp bl, es:[di]
- jne @@ChkFlag ;if not end of DestStr
- @@Exit:
- pop ax
- pop dx ;DX:AX->DestStr
- @PopRegs <ds, di, si>
- ret
- TEMPLSTR endp
-
- ;--------------------------------------------------------------------------
- ; NullPtr
- ;
- ; This is an internal support routine, visible only within this module.
- ;
- ; Determines whether the destination pointer passed to a string routine
- ; is null. If it is, NullPtr first pops the registers pushed by the
- ; string routine, then saves the return address of the __caller__ of
- ; the string routine, destroys the caller's stack frame, and returns
- ; to the caller with a null far pointer in DX:AX. If the pointer is
- ; not null, NullPtr jumps back to the string routine. At entry, the
- ; stack looks like this:
- ;
- ; +-----------+
- ; | Dest Segm |-\
- ; | Dest Offs |--\
- ; | Src Segm |---\ Pushed by caller of
- ; | Src Offs |----> string routine.
- ; | : |---/ (DX = size of stack frame)
- ; | : |--/
- ; |Parameter X|-/
- ; | CS |----\ Far return to caller
- ; | IP |----/ of string routine.
- ; | BP |---\
- ; | SI |----\ Pushed by string routine.
- ; | DI |----/
- ; | DS |---/
- ; |Ret Address|----> Return addr of string routine.
- ; +-----------+
- ;
- ; Registers In Registers Out
- ; ---------------------------------- -----------------------------------
- ; ES:DI->destination string DX:AX = 0L if ES:DI NULL
- ; DX = size of parms to pop
- ; BP-> saved BP on stack
- ; SP-> return addr of string routine
- ;--------------------------------------------------------------------------
-
- NullPtr proc near
- pop bx ;BX = retn addr of string routine
- mov ax, es
- and ax, ax
- jz @@FarReturn ;if segment is 0
- and di, di
- jz @@FarReturn ;if offset is 0
- jmp bx ;ptr ok, return to string routine
- @@FarReturn:
- @PopRegs <ds, di, si> ;pop regs saved by string routine
- pop bp ;restore BP
- pop cx ;CX = return IP \ to caller of
- pop bx ;BX = return CS / string routine
- add sp, dx ;remove parms from stack
- sub ax, ax
- mov dx, ax ;DX:AX = (char *) NULL
- push bx ;restore far return
- push cx ; to caller of string routine
- retf ;to caller of string routine
- NullPtr endp
-
- ;--------------------------------------------------------------------------
- ; OpenLeft
- ;
- ; This is an internal support routine, visible only within this module.
- ;
- ; Opens space at the beginning of destination string so that,
- ; if destination and source strings are identical, routines that
- ; add to the beginning of the string can do so without overwriting
- ; any characters.
- ;
- ; Registers In Registers Out
- ; ---------------------------------- -----------------------------------
- ; BX = space to open in destination none
- ; CX = length of source string
- ; DS:SI->source string
- ; ES:DI->destination string
- ;--------------------------------------------------------------------------
-
- OpenLeft proc near
- uses bx, cx, ds, si, es, di
-
- add di, cx ;ES:DI->move from here
- mov si, es ;source is end of
- mov ds, si ; destination string
- mov si, di ;DS:SI->move from here
- add di, bx ;ES:DI->move to here
- inc cx ;move the null, too
- std
- rep movsb ;move CX chars BX places right
- cld
- ret
- OpenLeft endp
-
- ;--------------------------------------------------------------------------
- ; SameStr
- ;
- ; This is an internal support routine, visible only within this module.
- ;
- ; Check whether source and destination strings are identical.
- ;
- ; Registers In Registers Out
- ; ---------------------------------- -----------------------------------
- ; DS:SI->source string ZF = 1: strings same
- ; ES:DI->destination string
- ;--------------------------------------------------------------------------
-
- SameStr proc near
- uses ax, dx
-
- mov ax, ds
- mov dx, es
- xor ax, dx
- jnz @@Diff
- mov ax, si
- xor ax, di
- @@Diff:
- ret
- SameStr endp
-
- ;--------------------------------------------------------------------------
- ; StrLen
- ;
- ; This is an internal support routine, visible only within this module.
- ;
- ; Registers In Registers Out
- ; ---------------------------------- -----------------------------------
- ; DS:SI->string CX = length of string
- ;--------------------------------------------------------------------------
-
- StrLen proc near
- uses ax, di, es
-
- cld
- mov ax, ds
- mov es, ax
- mov di, si
- mov cx, 0FFFFh ;max scan (bytes)
- sub al, al ;look for null byte
- repne scasb
- inc cx
- not cx
- ret
- StrLen endp
-
- end
-
- ;**** EOF: STRINGZ.ASM ****
-